import GameView from "../../../../quick/core/ui/GameView";
import UILabel from "../../../../quick/core/ui/UILabel";
import { inject } from "../../../../quick/defines/Decorators";
import { Macro } from "../../../../quick/defines/Macros";

/**
 * @description 刮奖
 * @link 原项目地址 : https://github.com/ifengzp/cocos-awesome
 * 项目原理请参考
 * @see https://github.com/ifengzp/cocos-awesome/blob/master/doc/Scratch_ticket/Scratch_ticket.md
 */
const CALC_RECT_WIDTH = 40;
const CLEAR_LINE_WIDTH = 40;

const { ccclass, property } = cc._decorator;

@ccclass
export default class ScratchTicketView extends GameView {

    static getPrefabUrl() {
        return "prefabs/ScratchTicketView";
    }

    @inject("mask",cc.Node,"scratch")
    private maskNode: cc.Node = null;
    @inject("scratch",cc.Node)
    private ticketNode: cc.Node = null;
    @inject("progress",UILabel)
    private progress: UILabel = null;
    /**@description 辅助计算刮奖百分比 */
    private polygonPointsList: { rect: cc.Rect; isHit: boolean }[] = [];
    private tempDrawPoints: cc.Vec2[] = [];
    private calcDebugger: boolean = false; // 辅助开关，开启则会绘制划开涂层所属的小格子

    onLoad() {
        super.onLoad();
        this.onN(cc.find("goback", this.node),cc.Node.EventType.TOUCH_END, () => {
            this.enterBundle(Macro.BUNDLE_HALL);
        });
        this.onN(cc.find("button",this.node),cc.Node.EventType.TOUCH_END,this.reset);
        this.onN(this.ticketNode,cc.Node.EventType.TOUCH_START, this.touchStartEvent);
        this.onN(this.ticketNode,cc.Node.EventType.TOUCH_MOVE, this.touchMoveEvent);
        this.onN(this.ticketNode,cc.Node.EventType.TOUCH_END, this.touchEndEvent);
        this.onN(this.ticketNode,cc.Node.EventType.TOUCH_CANCEL, this.touchEndEvent);
        this.reset();
    }

    private touchStartEvent(event) {
        let point = this.ticketNode.convertToNodeSpaceAR(event.getLocation());
        this.clearMask(point);
    }

    private touchMoveEvent(event) {
        let point = this.ticketNode.convertToNodeSpaceAR(event.getLocation());
        this.clearMask(point);
    }

    private touchEndEvent() {
        this.tempDrawPoints = [];
        this.calcProgress();
    }

    private calcProgress() {
        let hitItemCount = 0;
        let ctx = this.ticketNode.getComponent(cc.Graphics);
        this.polygonPointsList.forEach((item) => {
            if (!item.isHit) return;
            hitItemCount += 1;

            if (!this.calcDebugger) return;
            ctx.rect(item.rect.x, item.rect.y, item.rect.width, item.rect.height);
            ctx.fillColor = cc.color(216, 18, 18, 255);
            ctx.fill();
        });

        this.progress.params = [Math.ceil((hitItemCount / this.polygonPointsList.length) * 100)];
    }

    private clearMask(pos) {
        let mask = this.maskNode.getComponent(cc.Mask);
        let stencil = mask._graphics;
        const len = this.tempDrawPoints.length;
        this.tempDrawPoints.push(pos);

        if (len <= 1) {
            // 只有一个点，用圆来清除涂层
            stencil.circle(pos.x, pos.y, CLEAR_LINE_WIDTH / 2);
            stencil.fill();

            // 记录点所在的格子
            this.polygonPointsList.forEach((item) => {
                if (item.isHit) return;
                const xFlag = pos.x > item.rect.x && pos.x < item.rect.x + item.rect.width;
                const yFlag = pos.y > item.rect.y && pos.y < item.rect.y + item.rect.height;
                if (xFlag && yFlag) item.isHit = true;
            });
        } else {
            // 存在多个点，用线段来清除涂层
            let prevPos = this.tempDrawPoints[len - 2];
            let curPos = this.tempDrawPoints[len - 1];

            stencil.moveTo(prevPos.x, prevPos.y);
            stencil.lineTo(curPos.x, curPos.y);
            stencil.lineWidth = CLEAR_LINE_WIDTH;
            stencil.lineCap = cc.Graphics.LineCap.ROUND;
            stencil.lineJoin = cc.Graphics.LineJoin.ROUND;
            stencil.strokeColor = cc.color(255, 255, 255, 255);
            stencil.stroke();

            // 记录线段经过的格子
            this.polygonPointsList.forEach((item) => {
                item.isHit = item.isHit || cc.Intersection.lineRect(prevPos, curPos, item.rect);
            });
        }
    }

    protected reset() {
        let mask: any = this.maskNode.getComponent(cc.Mask);
        mask._graphics.clear();

        this.tempDrawPoints = [];
        this.polygonPointsList = [];
        this.progress.params = [0];
        this.ticketNode.getComponent(cc.Graphics).clear();

        // 生成小格子，用来辅助统计涂层的刮开比例
        for (let x = 0; x < this.ticketNode.width; x += CALC_RECT_WIDTH) {
            for (let y = 0; y < this.ticketNode.height; y += CALC_RECT_WIDTH) {
                this.polygonPointsList.push({
                    rect: cc.rect(x - this.ticketNode.width / 2, y - this.ticketNode.height / 2, CALC_RECT_WIDTH, CALC_RECT_WIDTH),
                    isHit: false
                });
            }
        }
    }
}
